/*
 * Author: Rolando Fentanes
 * Class: CopyList
 * Contains methods to update a destination list with only new items
 * of a source list
 * This class copies one list into another without overwriting references
 * in the dest list. It also removes elements found in dest but not in src
 * Uses Collections.binarySearch so src list must be sorted.
 */

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CopyList {
    public static void copyList(List dest, List src) {
        copy(dest, src);

        // the remaining elements in src list will be those that were originally
        // in src but not in dest and so they need to be added
        dest.addAll(src);
    }

    public static void copyList(List dest, List src, Verify v) {
        copy(dest, src);

        // the remaining elements in src list will be those that were originally
        // in src but not in dest and so they need to be added
        addAll(dest, src, v);
    }

    public static void copyList(List dest, List src, Comparator c) {
        copy(dest, src, c);

        // the remaining elements in src list will be those that were originally
        // in src but not in dest and so they need to be added
        dest.addAll(src);
    }

    public static void copyList(List dest, List src, Comparator c, Verify v) {
        copy(dest, src, c);

        // the remaining elements in src list will be those that were originally
        // in src but not in dest and so they need to be added
        addAll(dest, src, v);
    }

    private static void copy(List dest, List src) {
        // go through dest list to search if every element is in the new list
        // travel backwards through dest because we will be removing elements from it
        for(int i = dest.size()-1; i >= 0 ; i--) {
            int src_i = Collections.binarySearch(src, dest.get(i));
            if(src_i >= 0)
                // if element is found in src list, remove it from src list
                src.remove(src_i);
            else
                // if element is NOT found in src list, remove it from dest list
                dest.remove(i);
        }
    }

    private static void copy(List dest, List src, Comparator c) {
        // go through dest list to search if every element is in the new list
        // travel backwards through dest because elements might be removed
        for(int i = dest.size()-1; i >= 0 ; i--) {
            int src_i = Collections.binarySearch(src, dest.get(i), c);
            if(src_i >= 0)
                // if element is found in src list, remove it from src list
                src.remove(src_i);
            else
                // if element is NOT found in src list, remove it from dest list
                dest.remove(i);
        }
    }

    private static void addAll(List dest, List src, Verify v) {
        // verify each element in src list before adding it to dest list
        for(Object o: src)
            if(v.verify(o))
                dest.add(o);
    }
}
